package com.itheima.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.common.enums.HttpCodeEnum;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.AppJwtUtil;
import com.itheima.common.util.RequestContextUtil;
import com.itheima.user.dto.LoginDto;
import com.itheima.user.dto.UserRelationDto;
import com.itheima.user.mapper.ApUserFanMapper;
import com.itheima.user.mapper.ApUserFollowMapper;
import com.itheima.user.pojo.ApUser;
import com.itheima.user.mapper.ApUserMapper;
import com.itheima.user.pojo.ApUserFan;
import com.itheima.user.pojo.ApUserFollow;
import com.itheima.user.service.ApUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @description <p>APP用户信息 业务实现</p>
 *
 * @version 1.0
 * @package com.itheima.user.service.impl
 */
@Service
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {

    @Autowired
    private ApUserFollowMapper apUserFollowMapper;

    @Autowired
    private ApUserFanMapper apUserFanMapper;


    /**
     * 1.app端用户登录校验
     *
     * @param dto
     * @return
     */
    @Override
    public Map<String, Object> loginCheck(LoginDto dto) {
        //1. 参数校验，防止空指针异常
        if (null==dto){
            throw new LeadNewsException(HttpCodeEnum.PARAM_REQUIRE);
        }
        Map<String,Object> resultMap = new HashMap<>();
        //2. 判断是否是匿名
        Long loginUserId = 0L;  //3. 是匿名 默认的用户id为0, 生成token返回
        if (StringUtils.isNotEmpty(dto.getPhone())&&StringUtils.isNotEmpty(dto.getPassword())){
            //4. 不是匿名，则要通过手机号码校验，密码
            ApUser loginUser = query().eq("phone",dto.getPhone()).one();
            if (null==loginUser){
                throw new LeadNewsException("手机号码或密码错误");
            }
            //密码
            String encryptedPwd = DigestUtils.md5DigestAsHex((dto.getPassword() + loginUser.getSalt()).getBytes());
            if (!loginUser.getPassword().equals(encryptedPwd)){
                // 密码不一致
                throw new LeadNewsException("手机号码或密码错误");
            }
            loginUserId = loginUser.getId().longValue();
            loginUser.setSalt(null);
            loginUser.setPassword(null);
            resultMap.put("user",loginUser);
        }
        //5. 校验通过后，生成token，返回user信息(密码、盐为空)
        String token = AppJwtUtil.createToken(loginUserId);
        resultMap.put("token",token);
        return resultMap;
    }

    /**
     * 2.关注与取消关注作者
     * @param dto
     */
    @Override
    @Transactional
    public void userFollow(UserRelationDto dto) {
        //1. 参数校验
        if (null==dto){
            throw new LeadNewsException(HttpCodeEnum.PARAM_INVALID);
        }
        //2. 匿名用户校验
        if (RequestContextUtil.isAnonymous()){
            throw new LeadNewsException(HttpCodeEnum.NEED_LOGIN);
        }
        //3. 取出作者id
        Integer authorId = dto.getAuthorId();
        //4. 取出登录用户id
        Integer loginUserId = Integer.parseInt(RequestContextUtil.getLoginUserId());
        //5. 判断是关注还是取消关注
        if (dto.getOperation()==0){
            //取消关注
            //5.1 如果是取消则删除记录
            //5.1.1 删除关注记录
            removeUserFollow(loginUserId,authorId);
            //5.1.1 删除粉丝记录
            removeFans(authorId,loginUserId);
        }else{
            //5.2 是否关注过了 报错关注过了
            LambdaQueryWrapper<ApUserFollow> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ApUserFollow::getUserId,loginUserId);
            queryWrapper.eq(ApUserFollow::getFollowId,authorId);
            ApUserFollow userFollow = apUserFollowMapper.selectOne(queryWrapper);
            if (null!=userFollow){
                throw new LeadNewsException("已经关注过了");
            }
            ApUser loginUser = getById(loginUserId);
            ApUser author = getById(authorId);
            //5.2.1. 添加关注记录
            addUserFollow(loginUserId,author);
            //5.2.2. 添加粉丝记录
            addUserFans(authorId,loginUser);
        }

    }


    /**
     * 2.1方法抽取-删除关注信息
     * delete from ap_user_follow where userId=loginUserId and follow_id=authorId
     * @param loginUserId
     * @param authorId
     */
    private void removeUserFollow(Integer loginUserId, Integer authorId) {
        LambdaQueryWrapper<ApUserFollow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApUserFollow::getUserId,loginUserId);
        queryWrapper.eq(ApUserFollow::getFollowId,authorId);
        apUserFollowMapper.delete(queryWrapper);

    }

    /**
     * 2.2方法抽取-删除粉丝
     * delete from ap_user_fans where userId=authorId and fans_id=loginUserId
     * @param authorId
     * @param loginUserId
     */
    private void removeFans(Integer authorId, Integer loginUserId) {
        LambdaQueryWrapper<ApUserFan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApUserFan::getUserId,authorId);
        queryWrapper.eq(ApUserFan::getFansId,loginUserId);
        apUserFanMapper.delete(queryWrapper);

    }

    //2.3方法抽取-添加关注记录
    private void addUserFollow(Integer loginUserId, ApUser author) {
        ApUserFollow follow = new ApUserFollow();
        follow.setUserId(loginUserId);
        follow.setFollowId(author.getId());
        follow.setFollowName(author.getName());
        follow.setLevel(1);  // 一般
        follow.setIsNotice(1);  // 要通知
        follow.setCreatedTime(LocalDateTime.now());
        apUserFollowMapper.insert(follow);

    }

    //2.4方法抽取-添加粉丝记录
    private void addUserFans(Integer authorId, ApUser loginUser) {
        ApUserFan fans = new ApUserFan();
        fans.setUserId(authorId);
        fans.setFansId(loginUser.getId());
        fans.setFansName(loginUser.getName());
        fans.setLevel(1);
        fans.setCreatedTime(LocalDateTime.now());
        fans.setIsDisplay(1);
        fans.setIsShieldComment(0);
        fans.setIsShieldLetter(0);
        apUserFanMapper.insert(fans);

    }
}
